/**
 * @file asdu_assembler.c
 * @brief ASDU组装器实现
 * @details 本文件实现了104协议的ASDU组装器功能，包括通用ASDU组装、遥信数据ASDU
 *          组装、遥测数据ASDU组装、控制命令ASDU组装、系统命令ASDU组装等核心功能。
 *          支持多种数据类型的信息对象组装，确保生成的ASDU数据符合104协议规范，
 *          包含完整的错误处理和参数验证。
 * 
 * @author zyb
 * @date 2025-10-07
 * @version 1.0
 * 
 * @note ASDU组装时需要确保信息对象数量在有效范围内（1-127）
 * @warning 不同类型的信息对象需要对应正确的类型标识
 * 
 * @see asdu_assembler.h
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#include "asdu_assembler.h"
#include <stdlib.h>
#include <string.h>
#include "../../common/types/include/protocol_types.h"
#include "../../common/types/include/constants.h"
#include "../../common/error/include/error_codes.h"
#include "../../../../../common/utils/include/buffer_utils.h"
#include "../../../../../common/logs/include/logger.h"

// 定义模块名称
#define LOG_MODULE_NAME "ASDU_ASSEMBLER"

/* ==================== 通用ASDU组装函数实现 ==================== */

/**
 * @brief 组装通用ASDU
 * @details 将ASDU结构体组装成字节流格式。ASDU包含类型标识、可变结构限定词、
 *          传送原因、公共地址、信息对象地址和信息对象数据等字段。
 *          函数会验证ASDU格式和缓冲区大小，然后将ASDU数据写入缓冲区。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为ASDU_HEADER_SIZE
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效ASDU类型
 * 
 * @note ASDU长度包括头部（6字节）和信息对象数据
 * @warning 缓冲区必须足够大以容纳完整的ASDU数据
 * 
 * @see asdu_t
 * @see validate_asdu
 * @see ASDU_HEADER_SIZE
 */
protocol_error_t assemble_asdu(const asdu_t* asdu, uint8_t* buffer, size_t buffer_size, size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "asdu=%p, buffer=%p, buffer_size=%zu, actual_size=%p", 
                   asdu, buffer, buffer_size, actual_size);
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU指针: %p, 缓冲区大小: %zu", asdu, buffer_size);
    
    if (asdu == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_NULL_POINTER");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始组装ASDU");
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU类型: %d, 长度: %d", asdu->type_id, asdu->length);
    
    if (buffer_size < ASDU_HEADER_SIZE) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < %d", buffer_size, ASDU_HEADER_SIZE);
        LOG_DEBUG(LOG_MODULE_NAME, "返回错误: PROTOCOL_ERROR_BUFFER_TOO_SMALL");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    /* 验证ASDU */
    LOG_DEBUG(LOG_MODULE_NAME, "开始验证ASDU格式");
    protocol_error_t result = validate_asdu(asdu);
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    size_t offset = 0;
    
    /* 写入类型标识 */
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, asdu->type_id));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    /* 写入可变结构限定词 */
    uint8_t vsq_byte = (asdu->vsq.sq << 7) | (asdu->vsq.number_of_objects & 0x7F);
    result = buffer_error_to_protocol_error(buffer_write_u8(buffer, offset++, vsq_byte));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    /* 写入传送原因（大端序） */
    result = buffer_error_to_protocol_error(buffer_write_u16(buffer, offset, asdu->cause_of_transmission, 1));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    offset += 2;
    
    /* 写入公共地址（大端序） */
    result = buffer_error_to_protocol_error(buffer_write_u16(buffer, offset, asdu->common_address, 1));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    offset += 2;
    
    /* 写入信息对象数据 */
    size_t info_object_size = asdu->length - ASDU_HEADER_SIZE;
    if (info_object_size > 0) {
        if (offset + info_object_size > buffer_size) {
            return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
        }
        
        if (asdu->info_object_data != NULL) {
            memcpy(buffer + offset, asdu->info_object_data, info_object_size);
            offset += info_object_size;
        }
    }
    
    *actual_size = offset;
    return PROTOCOL_SUCCESS;
}

/* ==================== 遥信数据ASDU组装函数实现 ==================== */

/**
 * @brief 组装单点信息ASDU
 * @details 组装单点信息（遥信）ASDU，用于传输开关量状态信息。
 *          支持M_SP_NA_1、M_SP_TA_1、M_SP_TB_1等类型标识。
 *          函数会验证参数有效性，构建ASDU结构，然后组装成字节流。
 * 
 * @param type_id 类型标识，如M_SP_NA_1、M_SP_TA_1等
 * @param cot 传送原因，如周期、突发、总召唤等
 * @param common_addr 公共地址，通常为1
 * @param info_objects 单点信息对象数组，不能为NULL
 * @param count 信息对象数量，范围1-127
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 单点信息包含地址、SIQ品质描述词和可选时间戳
 * @warning 信息对象数量必须在1-127范围内
 * 
 * @see single_point_info_t
 * @see siq_t
 * @see M_SP_NA_1
 * @see M_SP_TA_1
 */
protocol_error_t assemble_single_point_asdu(type_id_t type_id, 
                                           cause_of_transmission_t cot,
                                           asdu_common_address_t common_addr,
                                           const single_point_info_t* info_objects,
                                           uint8_t count,
                                           uint8_t* buffer,
                                           size_t buffer_size,
                                           size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装单点信息ASDU: type_id=%u, cot=%u, common_addr=%u, count=%u, buffer=%p, buffer_size=%zu", 
              type_id, cot, common_addr, count, buffer, buffer_size);
    
    if (info_objects == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (count == 0 || count > 127) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", count);
        return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + count * sizeof(single_point_info_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = type_id;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = count;
    asdu.cause_of_transmission = cot;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(count * sizeof(single_point_info_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", count * sizeof(single_point_info_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制信息对象数据 */
    memcpy(asdu.info_object_data, info_objects, count * sizeof(single_point_info_t));
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象数据复制完成: %u个对象", count);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "单点信息ASDU组装成功: type_id=%u, count=%u, actual_size=%zu", 
             type_id, count, *actual_size);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 组装双点信息ASDU
 * @details 组装双点信息（遥信）ASDU，用于传输双点开关量状态信息。
 *          支持M_DP_NA_1、M_DP_TA_1、M_DP_TB_1等类型标识。
 *          函数会验证参数有效性，构建ASDU结构，然后组装成字节流。
 * 
 * @param type_id 类型标识，如M_DP_NA_1、M_DP_TA_1等
 * @param cot 传送原因，如周期、突发、总召唤等
 * @param common_addr 公共地址，通常为1
 * @param info_objects 双点信息对象数组，不能为NULL
 * @param count 信息对象数量，范围1-127
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 双点信息包含地址、DIQ品质描述词和可选时间戳
 * @warning 信息对象数量必须在1-127范围内
 * 
 * @see double_point_info_t
 * @see diq_t
 * @see M_DP_NA_1
 * @see M_DP_TA_1
 */
protocol_error_t assemble_double_point_asdu(type_id_t type_id, 
                                           cause_of_transmission_t cot,
                                           asdu_common_address_t common_addr,
                                           const double_point_info_t* info_objects,
                                           uint8_t count,
                                           uint8_t* buffer,
                                           size_t buffer_size,
                                           size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装双点信息ASDU: type_id=%u, cot=%u, common_addr=%u, count=%u, buffer=%p, buffer_size=%zu", 
              type_id, cot, common_addr, count, buffer, buffer_size);
    
    if (info_objects == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (count == 0 || count > 127) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", count);
        return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + count * sizeof(double_point_info_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = type_id;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = count;
    asdu.cause_of_transmission = cot;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(count * sizeof(double_point_info_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", count * sizeof(double_point_info_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制信息对象数据 */
    memcpy(asdu.info_object_data, info_objects, count * sizeof(double_point_info_t));
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象数据复制完成: %u个对象", count);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "双点信息ASDU组装成功: type_id=%u, count=%u, actual_size=%zu", 
             type_id, count, *actual_size);
    return PROTOCOL_SUCCESS;
}

/* ==================== 遥测数据ASDU组装函数实现 ==================== */

/**
 * @brief 组装测量值ASDU
 * @details 组装测量值（遥测）ASDU，用于传输模拟量测量数据。
 *          支持M_ME_NA_1、M_ME_NB_1、M_ME_NC_1等类型标识。
 *          函数会验证参数有效性，构建ASDU结构，然后组装成字节流。
 * 
 * @param type_id 类型标识，如M_ME_NA_1、M_ME_NB_1、M_ME_NC_1等
 * @param cot 传送原因，如周期、突发、总召唤等
 * @param common_addr 公共地址，通常为1
 * @param info_objects 测量值信息对象数组，不能为NULL
 * @param count 信息对象数量，范围1-127
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 测量值包含地址、数值、QDS品质描述词和可选时间戳
 * @warning 信息对象数量必须在1-127范围内
 * 
 * @see measurement_info_t
 * @see qds_t
 * @see M_ME_NA_1
 * @see M_ME_NB_1
 * @see M_ME_NC_1
 */
protocol_error_t assemble_measurement_asdu(type_id_t type_id, 
                                          cause_of_transmission_t cot,
                                          asdu_common_address_t common_addr,
                                          const measurement_info_t* info_objects,
                                          uint8_t count,
                                          uint8_t* buffer,
                                          size_t buffer_size,
                                          size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装测量值ASDU: type_id=%u, cot=%u, common_addr=%u, count=%u, buffer=%p, buffer_size=%zu", 
              type_id, cot, common_addr, count, buffer, buffer_size);
    
    if (info_objects == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (count == 0 || count > 127) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", count);
        return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + count * sizeof(measurement_info_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = type_id;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = count;
    asdu.cause_of_transmission = cot;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(count * sizeof(measurement_info_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", count * sizeof(measurement_info_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制信息对象数据 */
    memcpy(asdu.info_object_data, info_objects, count * sizeof(measurement_info_t));
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象数据复制完成: %u个对象", count);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "测量值ASDU组装成功: type_id=%u, count=%u, actual_size=%zu", 
             type_id, count, *actual_size);
    return PROTOCOL_SUCCESS;
}

/* ==================== 控制命令ASDU组装函数实现 ==================== */

/**
 * @brief 组装单命令ASDU
 * @details 组装单命令ASDU，用于传输单点控制命令。支持C_SC_NA_1类型标识。
 *          函数会验证参数有效性，构建ASDU结构，然后组装成字节流。
 *          单命令用于控制单点开关量设备。
 * 
 * @param cot 传送原因，如激活、激活确认、停止激活等
 * @param common_addr 公共地址，通常为1
 * @param info_objects 单命令信息对象数组，不能为NULL
 * @param count 信息对象数量，范围1-127
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 单命令包含地址、SCO控制命令和可选时间戳
 * @warning 信息对象数量必须在1-127范围内
 * 
 * @see single_command_info_t
 * @see sco_t
 * @see C_SC_NA_1
 */
protocol_error_t assemble_single_command_asdu(cause_of_transmission_t cot,
                                             asdu_common_address_t common_addr,
                                             const single_command_info_t* info_objects,
                                             uint8_t count,
                                             uint8_t* buffer,
                                             size_t buffer_size,
                                             size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装单点命令ASDU: cot=%u, common_addr=%u, count=%u, buffer=%p, buffer_size=%zu", 
              cot, common_addr, count, buffer, buffer_size);
    
    if (info_objects == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (count == 0 || count > 127) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", count);
        return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + count * sizeof(single_command_info_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = TYPE_ID_SINGLE_COMMAND;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = count;
    asdu.cause_of_transmission = cot;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(count * sizeof(single_command_info_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", count * sizeof(single_command_info_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制信息对象数据 */
    memcpy(asdu.info_object_data, info_objects, count * sizeof(single_command_info_t));
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象数据复制完成: %u个对象", count);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "单点命令ASDU组装成功: cot=%u, count=%u, actual_size=%zu", 
             cot, count, *actual_size);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 组装双命令ASDU
 * @details 组装双命令（遥控）ASDU，用于传输双点控制命令。
 *          支持C_DC_NA_1类型标识。函数会验证参数有效性，
 *          构建ASDU结构，然后组装成字节流。
 * 
 * @param cot 传送原因，如请求、激活等
 * @param common_addr 公共地址，通常为1
 * @param info_objects 双命令信息对象数组，不能为NULL
 * @param count 信息对象数量，范围1-127
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_INVALID_PARAM: 无效参数
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 双命令包含地址、DCO控制命令和可选时间戳
 * @warning 信息对象数量必须在1-127范围内
 * 
 * @see double_command_info_t
 * @see dco_t
 * @see C_DC_NA_1
 */
protocol_error_t assemble_double_command_asdu(cause_of_transmission_t cot,
                                             asdu_common_address_t common_addr,
                                             const double_command_info_t* info_objects,
                                             uint8_t count,
                                             uint8_t* buffer,
                                             size_t buffer_size,
                                             size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装双点命令ASDU: cot=%u, common_addr=%u, count=%u, buffer=%p, buffer_size=%zu", 
              cot, common_addr, count, buffer, buffer_size);
    
    if (info_objects == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (count == 0 || count > 127) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", count);
        return PROTOCOL_ERROR_INVALID_PARAM;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + count * sizeof(double_command_info_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = TYPE_ID_DOUBLE_COMMAND;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = count;
    asdu.cause_of_transmission = cot;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(count * sizeof(double_command_info_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", count * sizeof(double_command_info_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制信息对象数据 */
    memcpy(asdu.info_object_data, info_objects, count * sizeof(double_command_info_t));
    LOG_DEBUG(LOG_MODULE_NAME, "信息对象数据复制完成: %u个对象", count);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "双点命令ASDU组装成功: cot=%u, count=%u, actual_size=%zu", 
             cot, count, *actual_size);
    return PROTOCOL_SUCCESS;
}

/* ==================== 系统命令ASDU组装函数实现 ==================== */

/**
 * @brief 组装总召唤ASDU
 * @details 组装总召唤ASDU，用于请求站端发送所有数据。
 *          支持C_IC_NA_1类型标识。函数会验证参数有效性，
 *          构建ASDU结构，然后组装成字节流。
 * 
 * @param common_addr 公共地址，通常为1
 * @param qoi 限定词，指定召唤范围
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 * 
 * @note 总召唤ASDU包含QOI限定词
 * @warning QOI必须是有效的限定词值
 * 
 * @see qoi_t
 * @see C_IC_NA_1
 */
protocol_error_t assemble_total_interrogation_asdu(asdu_common_address_t common_addr,
                                                  qoi_t qoi,
                                                  uint8_t* buffer,
                                                  size_t buffer_size,
                                                  size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装总召唤ASDU: common_addr=%u, qoi=%u, buffer=%p, buffer_size=%zu", 
              common_addr, qoi, buffer, buffer_size);
    
    if (buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + sizeof(qoi);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    protocol_error_t result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = TYPE_ID_TOTAL_INTERROGATION;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = 1;
    asdu.cause_of_transmission = COT_REQUEST;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(sizeof(qoi));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", sizeof(qoi));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制QOI数据 */
    memcpy(asdu.info_object_data, &qoi, sizeof(qoi));
    LOG_DEBUG(LOG_MODULE_NAME, "QOI数据复制完成: qoi=%u", qoi);
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "总召唤ASDU组装成功: common_addr=%u, qoi=%u, actual_size=%zu", 
             common_addr, qoi, *actual_size);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 组装时钟同步ASDU
 * @details 组装时钟同步ASDU，用于请求站端同步时钟。
 *          支持C_CS_NA_1类型标识。函数会验证时间戳有效性，
 *          构建ASDU结构，然后组装成字节流。
 * 
 * @param common_addr 公共地址，通常为1
 * @param timestamp 时间戳，不能为NULL
 * @param buffer 输出缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param actual_size 实际写入的字节数输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 组装成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_MEMORY_ALLOCATION: 内存分配失败
 *         - PROTOCOL_ERROR_INVALID_TIMESTAMP: 无效时间戳
 * 
 * @note 时钟同步ASDU包含CP56Time2a时间戳
 * @warning 时间戳必须是有效的CP56Time2a格式
 * 
 * @see cp56time2a_t
 * @see validate_cp56time2a
 * @see C_CS_NA_1
 */
protocol_error_t assemble_clock_sync_asdu(asdu_common_address_t common_addr,
                                         const cp56time2a_t* timestamp,
                                         uint8_t* buffer,
                                         size_t buffer_size,
                                         size_t* actual_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "组装时钟同步ASDU: common_addr=%u, timestamp=%p, buffer=%p, buffer_size=%zu", 
              common_addr, timestamp, buffer, buffer_size);
    
    if (timestamp == NULL || buffer == NULL || actual_size == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证时间戳 */
    protocol_error_t result = validate_cp56time2a(timestamp);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳验证失败: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳验证通过");
    
    /* 计算所需缓冲区大小 */
    size_t required_size = ASDU_HEADER_SIZE + sizeof(cp56time2a_t);
    if (buffer_size < required_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: 需要%zu字节，提供%zu字节", required_size, buffer_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "缓冲区大小验证通过: 需要%zu字节", required_size);
    
    /* 构建ASDU */
    asdu_t asdu;
    result = init_asdu(&asdu);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU初始化失败: %d", result);
        return result;
    }
    
    /* 设置ASDU头部 */
    asdu.type_id = TYPE_ID_CLOCK_SYNC;
    asdu.vsq.sq = 0; /* 非连续结构 */
    asdu.vsq.number_of_objects = 1;
    asdu.cause_of_transmission = COT_REQUEST;
    asdu.common_address = common_addr;
    asdu.length = required_size;
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU头部设置完成: type_id=%u, vsq=%u, cot=%u, common_addr=%u, length=%u", 
              asdu.type_id, asdu.vsq.number_of_objects, asdu.cause_of_transmission, asdu.common_address, asdu.length);
    
    /* 分配信息对象数据缓冲区 */
    asdu.info_object_data = (uint8_t*)malloc(sizeof(cp56time2a_t));
    if (asdu.info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "内存分配失败: %zu字节", sizeof(cp56time2a_t));
        return PROTOCOL_ERROR_MEMORY_ALLOCATION;
    }
    
    /* 复制时间戳数据 */
    memcpy(asdu.info_object_data, timestamp, sizeof(cp56time2a_t));
    LOG_DEBUG(LOG_MODULE_NAME, "时间戳数据复制完成");
    
    /* 组装ASDU */
    result = assemble_asdu(&asdu, buffer, buffer_size, actual_size);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU组装失败: %d", result);
        free(asdu.info_object_data);
        return result;
    }
    
    /* 清理资源 */
    free(asdu.info_object_data);
    
    LOG_INFO(LOG_MODULE_NAME, "时钟同步ASDU组装成功: common_addr=%u, actual_size=%zu", 
             common_addr, *actual_size);
    return PROTOCOL_SUCCESS;
}
